#include "msa9020.h"

Msa9020::Msa9020(QObject *parent) : QObject(parent)
{

}


void Msa9020::initMsa(QString iniFile, QWidget *p)
{
    QSettings configIni(iniFile, QSettings::IniFormat);
    cards.clear();

    // 从配置文件中初始化CARDS
    for(int i=1; i<=MAX_CARDS_COUNT; i++) {
        CARDS card;
        card.index = i;
        quint8 addr     = configIni.value("msa/addr" + QString::number(i), 0).toInt();
        card.aname      = configIni.value("msa/a" + QString::number(i), tr("未使用A")).toString();
        card.bname      = configIni.value("msa/b" + QString::number(i), tr("未使用B")).toString();
        // 将显示控制指针连接到界面上的显示控件
        card.labelModbusAddr = p->findChild<QLabel*>("modbusAddr"+QString::number(i));
        card.labelAddrA      = p->findChild<QLabel*>("addrA"+QString::number(i));
        card.labelAddrB      = p->findChild<QLabel*>("addrB"+QString::number(i));
        card.labelCHA_value  = p->findChild<QLabel*>("CHA_value_"+QString::number(i));
        card.labelCHB_value  = p->findChild<QLabel*>("CHB_value_"+QString::number(i));
        card.labelAc         = p->findChild<QLabel*>("Ac_"+QString::number(i));
        card.labelBc         = p->findChild<QLabel*>("Bc_"+QString::number(i));
        card.labelAf         = p->findChild<QLabel*>("Af_"+QString::number(i));
        card.labelBf         = p->findChild<QLabel*>("Bf_"+QString::number(i));
        card.labelAl         = p->findChild<QLabel*>("Al_"+QString::number(i));
        card.labelBl         = p->findChild<QLabel*>("Bl_"+QString::number(i));
        card.labelAh         = p->findChild<QLabel*>("Ah_"+QString::number(i));
        card.labelBh         = p->findChild<QLabel*>("Bh_"+QString::number(i));

        card.labelModbusAddr->setText("Modbus: "+QString::number(addr));
        //card.labelModbusAddr->setMaximumSize(85,27);

        card.labelAddrA->setText(card.aname);
        //card.labelAddrA->setMaximumSize(85,28);

        card.labelAddrB->setText(card.bname);
        //card.labelAddrB->setMaximumSize(85,28);

        //card.labelCHA_value->setMaximumSize(85,29);
        //card.labelCHB_value->setMaximumSize(85,29);

        card.aa = false;
        card.ab = false;
        card.fa = false;
        card.fb = false;
        card.da = false;
        card.db = false;
        card.ea = false;
        card.eb = false;
        card.ca = false;
        card.cb = false;
        card.wa = false;
        card.wb = false;
        card.e1a = false;
        card.e1b = false;
        card.e2a = false;
        card.e2b = false;
        card.e3a = false;
        card.e3b = false;
        card.e4a = false;
        card.e4b = false;

        // 将MODBUS地址不为0的通道卡，建立队列
        if(addr>0)
            cards.insert(addr, card);
    }
    otcount = configIni.value("sys/overtimecount", 10).toInt();
}


/* 功能：设置MSA9020卡A通道测量单位
 * 参数：key，从机Modbus地址（0~255）
 *      value,0:ELE，1:ELEm，2:PPM，3:VOL，4:g/m3  */
void Msa9020::setUnitMeasurCha(quint8 key, quint16 value) {
    if(value<=4) cards[key].unit_measur_cha = value;
}

/* 功能：设置MSA9020卡B通道测量单位
 * 参数：key，从机Modbus地址（0~255）
 *      value,0:ELE，1:ELEm，2:PPM，3:VOL，4:g/m3  */
void Msa9020::setUnitMeasurChb(quint8 key, quint16 value) {
    if(value<=4) cards[key].unit_measur_chb = value;
}

/* 功能：设置MSA9020卡A通道名称
 * 参数：key，从机Modbus地址（0~255）
 *      name, 表示传感器浓度值的安装区域  */
void  Msa9020::setNameCha(quint8 key, QString name) {
    cards[key].aname = name;
}

/* 功能：设置MSA9020卡B通道名称
 * 参数：key，从机Modbus地址（0~255）
 *      name, 表示传感器浓度值的安装区域  */
void  Msa9020::setNameChb(quint8 key, QString name) {
    cards[key].bname = name;
}

/* 功能：从机地址为key值是否在CARDS中
 * 参数：key，从机Modbus地址（0~255） */
bool Msa9020::contains(quint8 key) {
    return cards.contains(key);
}

/* 功能：取得从机地址为key的A通道浓度值，带单位的字符串类型
 * 参数：key，从机Modbus地址（0~255） */
QString Msa9020::getValueStrCha(quint8 key) {
    float v = (cards[key].ci.v_real_cha * 1.0) / qPow(10, cards[key].ci.decimal_cha); // 值计算： value / (10^decimals)
    return "<font color='#00ff00'><b>"+QString::number(v,'f', cards[key].ci.decimal_cha)+\
           "</b></font><font color='#ffff00' size='-4'>" + UMC[cards[key].unit_measur_cha] + "</font>";
}

/* 功能：取得从机地址为key的B通道浓度值，带单位的字符串类型
 * 参数：key，从机Modbus地址（0~255） */
QString Msa9020::getValueStrChb(quint8 key) {
    float v = (cards[key].ci.v_real_chb * 1.0) / qPow(10, cards[key].ci.decimal_chb);
    return "<font color='#00ff00'><b>"+QString::number(v,'f', cards[key].ci.decimal_chb)+\
           "</b></font><font color='#ffff00' size='-4'>" + UMC[cards[key].unit_measur_chb]+"</font>";
}

/* 功能：取得从机地址为key的A通道浓度值，浮点类型
 * 参数：key，从机Modbus地址（0~255） */
float Msa9020::getValueCha(quint8 key) {
    return (cards[key].ci.v_real_cha * 1.0) / qPow(10, cards[key].ci.decimal_cha);
}

/* 功能：取得从机地址为key的B通道浓度值，浮点类型
 * 参数：key，从机Modbus地址（0~255） */
float Msa9020::getValueChb(quint8 key) {
    return (cards[key].ci.v_real_chb * 1.0) / qPow(10, cards[key].ci.decimal_chb);
}

/* 功能：取得从机地址为key的A通道故障详细信息*/
QString Msa9020::getStateFailInfoCha(quint8 key) {
    QString state[9] = {"no failure",
                        "电源线路故障",
                        "输入信号故障",
                        "存储器（EEPROM）程序出错",
                        "操作功能码时系统掉电",
                        "模拟信号相关的A/D转换器故障",
                        "存储器（RAM)故障",
                        "只读存储器（EPROM）产生错误",
                        "控制器内随机存储器数据设置发生错误"
                       };
    int i = cards[key].ci.state_fail_cha;
    i = i<9 ? i : 0;
    return state[i];
}

/* 功能：取得从机地址为key的B通道故障详细信息*/
QString Msa9020::getStateFailInfoChb(quint8 key) {
    QString state[9] = {"no failure",
                        "电源线路故障",
                        "输入信号故障",
                        "存储器（EEPROM）程序出错",
                        "操作功能码时系统掉电",
                        "模拟信号相关的A/D转换器故障",
                        "存储器（RAM)故障",
                        "只读存储器（EPROM）产生错误",
                        "控制器内随机存储器数据设置发生错误"
                       };
    int i = cards[key].ci.state_fail_chb;
    i = i<9 ? i : 0;
    return state[i];
}

/* 功能：取得从机地址为key的A通道故障代码
 * 参数：key，从机Modbus地址（0~255）
 * 返回值 ：
    0   //no failure
    1   // 电源线路故障
    2   // 输入信号故障
    3   // 存储器（EEPROM）程序出错
    4   // 操作功能码时系统掉电
    5   // 模拟信号相关的A/D转换器故障
    6   // 存储器（RAM)故障
    7   // 只读存储器（EPROM）产生错误
    8   // 控制器内随机存储器数据设置发生错误 */
QString Msa9020::getStateFailStrCha(quint8 key) {
    QString state[9] = {"NF","F1","F2","F3","F4","F5","F6","F7","F8"};
    int i = cards[key].ci.state_fail_cha;
    i = i<9 ? i : 0;
    return "<font color='#ff0000'><b>"+state[i]+"</b></font>";
}

/* 功能：取得从机地址为key的B通道故障代码
 * 参数：key，从机Modbus地址（0~255）
 * 返回值：
    0   //no failure
    1   // 电源线路故障
    2   // 输入信号故障
    3   // 存储器（EEPROM）程序出错
    4   // 操作功能码时系统掉电
    5   // 模拟信号相关的A/D转换器故障
    6   // 存储器（RAM)故障
    7   // 只读存储器（EPROM）产生错误
    8   // 控制器内随机存储器数据设置发生错误 */
QString Msa9020::getStateFailStrChb(quint8 key) {
    QString state[9] = {"NF","F1","F2","F3","F4","F5","F6","F7","F8"};
    int i = cards[key].ci.state_fail_chb;
    i = i<9 ? i : 0;
    return "<font color='#ff0000'><b>"+state[i]+"</b></font>";
}

/* 功能：取得从机地址为key的A通道是否有故障
 * 参数：key，从机Modbus地址（0~255）
 * 返回值 ：
    0   // 无故障
    1   // 有故障 */
int Msa9020::getStateFailCha(quint8 key) {
    return cards[key].ci.state_fail_cha;
}

/* 功能：取得从机地址为key的B通道是否有故障
 * 参数：key，从机Modbus地址（0~255）
 * 返回值：
    0   // 无故障
    1   // 有故障 */
int Msa9020::getStateFailChb(quint8 key) {
    return cards[key].ci.state_fail_chb;
}

/* 功能：取得从机地址为key的A通道漂移信息
 * 参数：key，从机Modbus地址（0~255）
 * 返回值： 0  无漂移
          <>0 漂移*/
int Msa9020::getStateDriftCha(quint8 key) {
    return cards[key].ci.state_drift_cha;
}

/* 功能：取得从机地址为key的B通道漂移信息
 * 参数：key，从机Modbus地址（0~255）
 * 返回值:  0  无漂移
          <>0 漂移                */
int Msa9020::getStateDriftChb(quint8 key) {
    return cards[key].ci.state_drift_chb;
}

/* 功能：取得从机地址为key的A通道是否超量程
 * 参数：key，从机Modbus地址（0~255）
 * 返回值: 0  没超量程
          1  超量程                */
int Msa9020::getStateEEEECha(quint8 key) {
    return cards[key].ci.state_eeee_cha;
}

/* 功能：取得从机地址为key的B通道是否超量程
 * 参数：key，从机Modbus地址（0~255）
 * 返回值: 0  没超量程
          1  超量程                */
int Msa9020::getStateEEEEChb(quint8 key) {
    return cards[key].ci.state_eeee_chb;
}

/* 功能：取得从机地址为key的A通道“小心”报警状态
 * 参数：key，从机Modbus地址（0~255）
 * 返回值: 0  无小心报警
          1  产生小心报警                */
int Msa9020::getCautionCha(quint8 key) {
    return cards[key].ci.state_c_cha;
}

/* 功能：取得从机地址为key的B通道“小心”报警状态
 * 参数：key，从机Modbus地址（0~255）
 * 返回值: 0  无小心报警
          1  产生小心报警                */
int Msa9020::getCautionChb(quint8 key) {
    return cards[key].ci.state_c_chb;
}

/* 功能：取得从机地址为key的A通道“预报警”状态
 * 参数：key，从机Modbus地址（0~255）
 * 返回值: 0  无预报警
          1  产生预报警                */
int Msa9020::getWarningCha(quint8 key) {
    return cards[key].ci.state_w_cha;
}

/* 功能：取得从机地址为key的B通道“预报警”状态
 * 参数：key，从机Modbus地址（0~255）
 * 返回值: 0  无预报警
          1  产生预报警                */
int Msa9020::getWarningChb(quint8 key) {
    return cards[key].ci.state_w_chb;
}

/* 功能：取得从机地址为key的A通道“高报警”状态
 * 参数：key，从机Modbus地址（0~255）
 * 返回值: 0  无高报警
          1  产生高报警                */
int Msa9020::getAlarmCha(quint8 key) {
    return cards[key].ci.state_a_cha;
}

/* 功能：取得从机地址为key的B通道“高报警”状态
 * 参数：key，从机Modbus地址（0~255）
 * 返回值: 0  无高报警
          1  产生高报警                */
int Msa9020::getAlarmChb(quint8 key) {
    return cards[key].ci.state_a_chb;
}

/* 功能：取得从机地址为key的A、B通道错误警告状态
 * 参数：key，从机Modbus地址（0~255）
 * 返回值: 0  无报警
          1  产生报警
 错误警告：
    E1  1  零信号和满量程之间的信号差<2mV
    E2  2  零信号和满量程之间的信号差>=200mV
    E3  3  零信号和满量程之间的信号差 3mV>n>2mV
    E4  4  输入信号高于 +300mV            */
int Msa9020::getErrorE1Cha(quint8 key) {
    return cards[key].ci.e1_cha;
}
int Msa9020::getErrorE1Chb(quint8 key) {
    return cards[key].ci.e1_chb;
}
int Msa9020::getErrorE2Cha(quint8 key) {
    return cards[key].ci.e2_cha;
}
int Msa9020::getErrorE2Chb(quint8 key) {
    return cards[key].ci.e2_chb;
}
int Msa9020::getErrorE3Cha(quint8 key) {
    return cards[key].ci.e3_cha;
}
int Msa9020::getErrorE3Chb(quint8 key) {
    return cards[key].ci.e3_chb;
}
int Msa9020::getErrorE4Cha(quint8 key) {
    return cards[key].ci.e4_cha;
}
int Msa9020::getErrorE4Chb(quint8 key) {
    return cards[key].ci.e4_chb;
}

/* 功能：更新显示界面MSA9020卡的浓度值和各种报警、故障状态
 * 参数： slaveAddr,从机MODBUS地址                */
void Msa9020::refreshDisplay(quint8 key)
{
    if(cards.contains(key)) {

        // 是否小心报警
        if(getCautionCha(key))  // A通道
            cards[key].labelAc->setStyleSheet("background-color: rgb(255, 0, 0);color: rgb(255, 255, 255);");
        else {
            cards[key].labelAc->setStyleSheet("background-color: rgb(85, 0, 0);color: rgb(255, 255, 255);");
            cards[key].ca = false; // 消除报警标志
        }

        if(getCautionChb(key)) // B通道
            cards[key].labelBc->setStyleSheet("background-color: rgb(255, 0, 0);color: rgb(255, 255, 255);");
        else {
            cards[key].labelBc->setStyleSheet("background-color: rgb(85, 0, 0);color: rgb(255, 255, 255);");
            cards[key].cb = false; // 消除报警标志
        }

        // 是否高报警
        if(getAlarmCha(key)) // A通道
            cards[key].labelAh->setStyleSheet("background-color: rgb(255, 0, 0);color: rgb(255, 255, 255);");
        else {
            cards[key].labelAh->setStyleSheet("background-color: rgb(85, 0, 0);color: rgb(255, 255, 255);");
            cards[key].aa = false; // 消除报警标志
        }

        if(getAlarmChb(key)) // B通道
            cards[key].labelBh->setStyleSheet("background-color: rgb(255, 0, 0);color: rgb(255, 255, 255);");
        else {
            cards[key].labelBh->setStyleSheet("background-color: rgb(85, 0, 0);color: rgb(255, 255, 255);");
            cards[key].ab = false; // 消除报警标志
        }

        // 是否预报警
        if(getWarningCha(key)) // A通道
            cards[key].labelAl->setStyleSheet("background-color: rgb(255, 0, 0);color: rgb(255, 255, 255);");
        else {
            cards[key].labelAl->setStyleSheet("background-color: rgb(85, 0, 0);color: rgb(255, 255, 255);");
            cards[key].wa = false; // 消除报警标志
        }

        if(getWarningChb(key)) // B通道
            cards[key].labelBl->setStyleSheet("background-color: rgb(255, 0, 0);color: rgb(255, 255, 255);");
        else {
            cards[key].labelBl->setStyleSheet("background-color: rgb(85, 0, 0);color: rgb(255, 255, 255);");
            cards[key].wb = false; // 消除报警标志
        }

        //  是否有故障
        if(getStateFailCha(key)) { // A通道
            cards[key].labelAf->setStyleSheet("background-color: rgb(255, 0, 0);color: rgb(255, 255, 255);");
            cards[key].labelCHA_value->setText(getStateFailStrCha(key)); // 显示故障码
        } else {
            cards[key].labelAf->setStyleSheet("background-color: rgb(85, 0, 0);color: rgb(255, 255, 255);");
            cards[key].labelCHA_value->setText(getValueStrCha(key));  // 显示实际值
            cards[key].fa = false; // 消除报警标志
        }

        if(getStateFailChb(key)) { // B通道
            cards[key].labelBf->setStyleSheet("background-color: rgb(255, 0, 0);color: rgb(255, 255, 255);");
            cards[key].labelCHB_value->setText(getStateFailStrChb(key)); // 显示故障码
        } else {
            cards[key].labelBf->setStyleSheet("background-color: rgb(85, 0, 0);color: rgb(255, 255, 255);");
            cards[key].labelCHB_value->setText(getValueStrChb(key));  // 显示实际值
            cards[key].fb = false; // 消除报警标志
        }

        // 是否超量程
        if(getStateEEEECha(key))  // A通道
            cards[key].labelCHA_value->setText("EEEE"); // 显示故障码
        else
            cards[key].ea = false; // 消除报警标志
        if(getStateEEEEChb(key))  // B通道
            cards[key].labelCHB_value->setText("EEEE"); // 显示故障码
        else
            cards[key].eb = false; // 消除报警标志

        // E1\E2\E3\E4错误信息
        if(getErrorE1Cha(key))  // A通道
            cards[key].labelCHA_value->setText("<font color='#ff0000'><b>E1</b></font>"); // 显示错误码
        else
            cards[key].e1a = false; // 消除报警标志
        if(getErrorE1Chb(key))  // B通道
            cards[key].labelCHB_value->setText("<font color='#ff0000'><b>E1</b></font>"); // 显示错误码
        else
            cards[key].e1b = false; // 消除报警标志

        if(getErrorE2Cha(key))  // A通道
            cards[key].labelCHA_value->setText("<font color='#ff0000'><b>E2</b></font>"); // 显示错误码
        else
            cards[key].e2a = false; // 消除报警标志
        if(getErrorE2Chb(key))  // B通道
            cards[key].labelCHB_value->setText("<font color='#ff0000'><b>E2</b></font>"); // 显示错误码
        else
            cards[key].e2b = false; // 消除报警标志

        if(getErrorE3Cha(key))  // A通道
            cards[key].labelCHA_value->setText("<font color='#ff0000'><b>E3</b></font>"); // 显示错误码
        else
            cards[key].e3a = false; // 消除报警标志
        if(getErrorE3Chb(key))  // B通道
            cards[key].labelCHB_value->setText("<font color='#ff0000'><b>E3</b></font>"); // 显示错误码
        else
            cards[key].e3b = false; // 消除报警标志

        if(getErrorE4Cha(key))  // A通道
            cards[key].labelCHA_value->setText("<font color='#ff0000'><b>E4</b></font>"); // 显示错误码
        else
            cards[key].e4a = false; // 消除报警标志
        if(getErrorE4Chb(key))  // B通道
            cards[key].labelCHB_value->setText("<font color='#ff0000'><b>E4</b></font>"); // 显示错误码
        else
            cards[key].e4b = false; // 消除报警标志

        if(!getStateDriftCha(key))
            cards[key].da = false; // 消除报警标志
        if(!getStateDriftChb(key))
            cards[key].db = false; // 消除报警标志

        cards[key].overtimeCount =0;  // 超时计数归0
    }
}

// 显示超时状态
void Msa9020::displayOvertime(quint8 key)
{
    cards[key].overtimeCount++; // 超时计数增1
    if(cards[key].overtimeCount > otcount) {
        cards[key].labelCHA_value->setText("overtime");
        cards[key].labelCHB_value->setText("overtime");
    }
}


int Msa9020::getChIndex(quint8 key)
{
    return cards[key].index;
}

QString Msa9020::getUnitMeasurCha(quint8 key)
{
    return UMC[cards[key].unit_measur_cha];
}

QString Msa9020::getUnitMeasurChb(quint8 key)
{
    return UMC[cards[key].unit_measur_chb];
}

void Msa9020::setAlarmState(quint8 key)
{
    if(cards[key].aa  && (cards[key].ci.state_a_cha == 0))        cards[key].aa  = false;
    if(cards[key].ab  && (cards[key].ci.state_a_chb == 0))        cards[key].ab  = false;
    if(cards[key].fa  && (cards[key].ci.state_fail_cha == 0))     cards[key].fa  = false;
    if(cards[key].fb  && (cards[key].ci.state_fail_chb == 0))     cards[key].fb  = false;
    if(cards[key].da  && (cards[key].ci.state_drift_cha == 0))    cards[key].da  = false;
    if(cards[key].db  && (cards[key].ci.state_drift_chb == 0))    cards[key].db  = false;
    if(cards[key].ea  && (cards[key].ci.state_eeee_cha == 0))     cards[key].ea  = false;
    if(cards[key].eb  && (cards[key].ci.state_eeee_chb == 0))     cards[key].eb  = false;
    if(cards[key].ca  && (cards[key].ci.state_c_cha == 0))        cards[key].ca  = false;
    if(cards[key].cb  && (cards[key].ci.state_c_chb == 0))        cards[key].cb  = false;
    if(cards[key].wa  && (cards[key].ci.state_w_cha == 0))        cards[key].wa  = false;
    if(cards[key].wb  && (cards[key].ci.state_w_chb == 0))        cards[key].wb  = false;
    if(cards[key].e1a && (cards[key].ci.e1_cha == 0))             cards[key].e1a = false;
    if(cards[key].e1b && (cards[key].ci.e1_chb == 0))             cards[key].e1b = false;
    if(cards[key].e2a && (cards[key].ci.e2_cha == 0))             cards[key].e2a = false;
    if(cards[key].e2b && (cards[key].ci.e2_chb == 0))             cards[key].e2b = false;
    if(cards[key].e3a && (cards[key].ci.e3_cha == 0))             cards[key].e3a = false;
    if(cards[key].e3b && (cards[key].ci.e3_chb == 0))             cards[key].e3b = false;
    if(cards[key].e4a && (cards[key].ci.e4_cha == 0))             cards[key].e4a = false;
    if(cards[key].e4b && (cards[key].ci.e4_chb == 0))             cards[key].e4b = false;

}
